<?php 
// +----------------------------------------------------------------------
// | RXThinkCMF_EVTP5.1_PRO前后端分离旗舰版框架 [ RXThinkCMF ]
// +----------------------------------------------------------------------
// | 版权所有 2018~2021 南京RXThinkCMF研发中心
// +----------------------------------------------------------------------
// | 官方网站: http://www.rxthink.cn
// +----------------------------------------------------------------------
// | 作者: 牧羊人 <rxthinkcmf@163.com>
// +----------------------------------------------------------------------
// | 免责声明:
// | 本软件框架禁止任何单位和个人用于任何违法、侵害他人合法利益等恶意的行为，禁止用于任何违
// | 反我国法律法规的一切平台研发，任何单位和个人使用本软件框架用于产品研发而产生的任何意外
// | 、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 (包括但不限于直接、间接、附带
// | 或衍生的损失等)，本团队不承担任何法律责任。本软件框架只能用于公司和个人内部的法律所允
// | 许的合法合规的软件产品研发，详细声明内容请阅读《框架免责声明》附件；
// +----------------------------------------------------------------------

namespace app\admin\service;


use app\admin\model\AttentionFactor;
use app\admin\model\AttentionResult;
use app\admin\model\AttentionSetting;
use app\admin\model\AttentionUser;
use app\admin\model\AttentionUserData;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use think\Exception;

/**
 * 专注力测评用户管理-服务类
 * @author 牧羊人
 * @since: 2024/02/26
 * Class AttentionUserService
 * @package app\admin\service
 */
class AttentionstatisticsService extends BaseService
{
    /**
     * 构造函数
     * LevelService constructor.
     */
    protected $userDataModel = null;
    protected $settingModel = null;
    protected $factorModel = null;
    protected $resultModel = null;
    public function __construct()
    {
        $this->model = new AttentionUser();
        $this->userDataModel = new AttentionUserData();
        $this->settingModel = new AttentionSetting();
        $this->factorModel = new AttentionFactor();
        $this->resultModel = new AttentionResult();
    }
	
	/**
     * 获取数据列表
     * @return array
     * @since 2024/02/26
     * @author 牧羊人
     */
    public function getList()
    {
        $param = request()->param();

        // 查询条件
        $map = [];
		
	
	    // 姓名
        $name = isset($param['name']) ? trim($param['name']) : '';
        if ($name) {
            $map[] = ['name', 'like', "%{$name}%"];
        }
		
	    // 性别
        $gender = isset($param['gender']) ? (int)$param['gender'] : 0;
        if ($gender) {
            $map[] = ['gender', '=', $gender];
        }

        // 联系方式
        $phone = isset($param['phone']) ? trim($param['phone']) : '';
        if ($phone) {
            $map[] = ['phone', 'like', "%{$phone}%"];
        }
        return parent::getList($map); // TODO: Change the autogenerated stub
    }


    public function stat()
    {
        // people: 100,
        // finish_people: 50,
        // boy_people: 20,
        // girl_people: 30,
        // avg_age: 5,
        // max_age: 6,
        // min_age: 3

        $people = $this->model->where('mark', 1)->count();
        $finish_people = $this->model->where('mark', 1)->where('is_finish', 1)->count();
        $boy_people = $this->model->where('mark', 1)->where('is_finish', 1)->where('gender', 1)->count();
        $girl_people = $this->model->where('mark', 1)->where('is_finish', 1)->where('gender', 2)->count();
        $max_age = $this->model->where('mark', 1)->where('is_finish', 1)->max('age');
        $min_age = $this->model->where('mark', 1)->where('is_finish', 1)->min('age');
        $avg_age = $this->model->where('mark', 1)->where('is_finish', 1)->avg('age');

        $pie = $this->resultModel->field("count(*) as value, result as name")->where('question_type', 0)->group('result')->select();

        $result = [
            'people' => $people,
            'finish_people' => $finish_people,
            'boy_people' => $boy_people,
            'girl_people' => $girl_people,
            'avg_age' => floor($avg_age),
            'max_age' => $max_age,
            'min_age' => $min_age,
            'pie' => $pie
        ];
        return message("操作成功", true, $result);
    }

    private function calcScoreByFactor($answers, $factorId)
    {
        $scores = [];
        if (!empty($answers)) {
            foreach ($answers as $answer) {
                if ($answer['question_type'] == $factorId) {
                    $scores[] = $answer['answer_score'];
                }
            }
        }
        return array_sum($scores);
    }

    private function calcResultByFactorScore($score, $rule)
    {
        foreach ($rule as $item) {
            if ($score >= $item['min'] && $score <= $item['max']) {
                return $item;
                break;
            }
        }
        return [];
    }

    public function getChartData()
    {
        try {

            $param    = request()->param();
            $dateType = getter($param, 'date_type', 1);
            $dateTime = getter($param, 'datetime', []);

            switch ($dateType) {
                case 1:
                    $data = $this->getChartDataForWeek();
                    break;
                case 2:
                    $data = $this->getChartDataForMonth();
                    break;
                case 3:
                    $data = $this->getChartDataForYear();
                    break;
                case 4:
                    $data = $this->getChartDataForLastMonth();
                    break;
                case 5:
                    $data = $this->getChartDataForLastWeek();
                    break;
                default:
                    $data = $this->getChartDataForPeriod($dateTime);
                    break;
            }

            $series = [
                ['label' => '男宝', 'value' => 1, 'key' => 'boy'],
                ['label' => '女宝', 'value' => 2, 'key' => 'girl']
            ];
            $result = [
                'series' => $series,
                'data'   => $data
            ];
            return message('查询成功', true, $result);
        } catch (Exception $exception) {
            return message($exception->getLine().$exception->getMessage(), false);
        }
    }

    private function getChartDataForWeek()
    {
        $monday = Carbon::now()->startOfWeek();
        $sunday = Carbon::now()->endOfWeek();
        $period = new CarbonPeriod($monday, '1 day', $sunday);
        return $this->_getChartData($period);
    }

    private function getChartDataForMonth()
    {
        $firstDay = Carbon::now()->startOfMonth();
        $endDay   = Carbon::now()->endOfMonth();
        $period   = new CarbonPeriod($firstDay, '1 day', $endDay);
        return $this->_getChartData($period);
    }

    private function getChartDataForYear()
    {
        $firstMonth = Carbon::now()->startOfYear();
        $endMonth   = Carbon::now()->endOfYear();
        $period     = new CarbonPeriod($firstMonth, '1 month', $endMonth);
        return $this->_getChartData($period, true);
    }

    private function getChartDataForLastMonth()
    {

        $lastMonthFirstDay = new Carbon('first day of last month');
        $lastMonthEndDay   = new Carbon('last day of last month');
        $period            = new CarbonPeriod($lastMonthFirstDay, '1 day', $lastMonthEndDay);
        return $this->_getChartData($period);
    }

    private function getChartDataForLastWeek()
    {

        $lastWeekFirstDay = Carbon::now()->subWeek()->startOfWeek();
        $lastWeekEndDay   = Carbon::now()->subWeek()->endOfWeek();
        $period           = new CarbonPeriod($lastWeekFirstDay, '1 day', $lastWeekEndDay);
        return $this->_getChartData($period);
    }

    private function getChartDataForPeriod($period)
    {
        $startDate = isset($period[0]) ? $period[0] : Carbon::now()->startOfWeek();
        $endDate   = isset($period[1]) ? $period[1] : Carbon::parse($startDate)->addDays(6);
        $period    = new CarbonPeriod($startDate, '1 day', $endDate);
        return $this->_getChartData($period);
    }

    private function _getChartData($period, $isMonth=false)
    {
        $sites = [
            ['label' => '男宝', 'value' => 1, 'key' => 'boy'],
            ['label' => '女宝', 'value' => 2, 'key' => 'girl']
        ];
        $data  = [];
        foreach ($period as $date) {
            $_date = !$isMonth ? $date->toDateString() : $date->format('Y-m');
            $total = [];
            foreach ($sites as $key => $site) {
                $totalKey = $site['key'];
                $pushData = $this->_getSitePushData($site['value'], $_date, $isMonth);
                $total[$totalKey]['count'] = $pushData['count'];
            }
            $data[] = array_merge(['date' => $_date], $total);
        }
        return $data;
    }

    public function _getSitePushData($siteId, $date='', $isMonth=false)
    {

        $filter = [];
        array_push($filter, ['gender', '=', $siteId]);
        array_push($filter, ['mark', '=', 1]);
        if (!empty($date)) {
            if (!$isMonth) {
                // $time = [strtotime($date.' 00:00:00'), strtotime($date.' 23:59:59')];
                // $filter['create_time'] = ['between', implode(',', $time)];
                array_push($filter, ['create_time', 'gt', strtotime($date.' 00:00:00')]);
                array_push($filter, ['create_time', 'lt', strtotime($date.' 23:59:59')]);
            } else {
                $d = Carbon::parse($date);
                // $time = [strtotime($d->firstOfMonth()->toDateTimeString()), strtotime($d->endOfMonth()->toDateTimeString())];
                // $filter['create_time'] = ['between', implode(',', $time)];
                array_push($filter, ['create_time', 'gt', strtotime($d->firstOfMonth()->toDateTimeString())]);
                array_push($filter, ['create_time', 'lt', strtotime($d->endOfMonth()->toDateTimeString())]);
            }
        }
        $data = $this->model->where($filter)->count();
        return [
            'count' => $data,
        ];
    }

    public function getChart2Data()
    {
        try {

            $param    = request()->param();
            $series = $this->factorModel->where('mark', 1)->order('weight', 'desc')->select();
            $_series = [];
            foreach ($series as $item) {
                $_series[] = $item['title'];
                // $yes = $this->resultModel->field("count(*) as value")->where('question_type', $item['id'])->where('result', '正常')->group('result')->select();
                // $no = $this->resultModel->field("count(*) as value")->whereIn('question_type', $item['id'])->where('result', '异常')->group('result')->select();
                // $data[] = [
                //     'name' => $item['title'],
                //     'type' => 'bar',
                //     'stack' => 'total',
                //     'label' => ['show' => true],
                //     'emphasis' => ['focus' => 'series'],
                //     'itemStyle' => ['color' => '#25b83b'],
                //     'data' => [$yes['value'], $no['value']],
                // ];
            }


            // echo $this->resultModel->getLastSql();
            // $no = $this->resultModel->field("count(*) as value")->whereIn('question_type', [1,2,3,4,5])->where('result', '异常')->group('question_type')->select();

            $yes = $this->getYesCount($series, '正常');
            $no = $this->getYesCount($series, '异常');

            $data = [
                [
                    'name' => '正常',
                    'type' => 'bar',
                    'stack' => 'total',
                    'label' => ['show' => true],
                    'emphasis' => ['focus' => 'series'],
                    'itemStyle' => ['color' => '#25b83b'],
                    'data' => $yes,
                ],
                [
                    'name' => '异常',
                    'type' => 'bar',
                    'stack' => 'total',
                    'label' => ['show' => true],
                    'emphasis' => ['focus' => 'series'],
                    'itemStyle' => ['color' => '#c23531'],
                    'data' => $no
                ]
            ];


            // $pie = $this->resultModel->field("count(*) as value, result as name")->where('question_type', 0)->group('result')->select();


            $result = [
                'series' => $data,
                'data'   => $_series
            ];
            return message('查询成功', true, $result);
        } catch (Exception $exception) {
            return message($exception->getLine().$exception->getMessage(), false);
        }
    }

    private function getYesCount($series, $type)
    {
        $data = [];
        foreach ($series as $item) {
            $count = $this->resultModel->field("count(*) as value")->where('question_type', $item['id'])->where('result', $type)->group('question_type')->find();
            $data[] = (!isset($count['value']) ||is_null($count['value'])) ? 0 : $count['value'];
        }
        return $data;
    }
}